﻿using System;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Web;
using SecurityClient;

namespace SecurityModule.Workflows
{
    class WFPostHomePasswordResetAction : SimpleWorkflow
    {
        public WFPostHomePasswordResetAction()
        {
            Verb = "POST";
            Path = "/Home/PasswordResetAction";
        }
        public override void PreProcessImplementation(HttpContext context)
        {
            // verify token, activate and add Email and ClientCode to Request.Form
            var callback = new Func<string, string>(formFields =>
                {
                    var fields = HttpUtility.ParseQueryString(formFields);

                    try
                    {
                        //Read fields
                        var tokenId = fields["Token"];
                        var action = fields["Action"];
                        var security = new SecurityServiceProxy();
                        switch (action)
                        {
                            case "Approve":
                                // no need for white-listing as the form contains no sensitive information
                                var email = security.GetTokenFieldValue(tokenId, "Username") as string;
                                if (string.IsNullOrEmpty(email))
                                {
                                    //Bubble up an error to the application
                                    fields.Add("EXTERRMSG", "Invalid token");
                                }
                                else
                                {
                                    var result = security.ApprovePasswordReset(tokenId);

                                    if (result.Success)
                                    {
                                        fields.Add("Password", result.Password);
                                        fields.Add("Email", email);
                                        //Store transactionId for later commit.
                                        context.Items["TransactionId"] = result.TransactionId;
                                    }
                                    else
                                    {
                                        //Bubble up an error to the application
                                        fields.Add("EXTERRMSG", result.ErrorMessage);
                                    }
                                }
                                break;
                            case "Disapprove":
                                // ignore it!
                                break;
                        }
                    }
                    catch (Exception exception)
                    {
                        if (exception is PipeException || exception is EndpointNotFoundException)
                        {
                            //If the security service is offline or broken
                            if (fields.AllKeys.Contains("EXTERRMSG"))
                            {
                                fields["EXTERRMSG"] = SecurityServiceDownMsg;
                            }
                            else
                            {
                                fields.Add("EXTERRMSG", SecurityServiceDownMsg);
                            }
                        }
                        else
                        {
                            if (fields.AllKeys.Contains("EXTERRMSG"))
                            {
                                fields["EXTERRMSG"] = exception.Message;
                            }
                            else
                            {
                                fields.Add("EXTERRMSG", exception.Message);
                            }
                        }
                    }
                    return fields.ToString();
                });
            context.Request.Filter = new RequestFilter(context.Request.Filter, context.Request.ContentEncoding, callback);
        }

        public override void PostProcessImplementation(HttpContext context)
        {
            if (context.Response.StatusCode != 200 && context.Response.StatusCode != 302) return;
            var transactionId = context.Items["TransactionId"];
            if (transactionId == null) return;
            try
            {
                var security = new SecurityServiceProxy();
                security.Commit((Guid)transactionId);
            }
            // ReSharper disable EmptyGeneralCatchClause
            catch
            // ReSharper restore EmptyGeneralCatchClause
            {
                //If the security service is offline or broken the swallow the exception
            }
        }
    }
}
